package com.lambkit.component.consul;

import java.util.List;
import java.util.Optional;

import com.google.common.net.HostAndPort;
import com.lambkit.Lambkit;
import com.orbitz.consul.AgentClient;
import com.orbitz.consul.Consul;
import com.orbitz.consul.HealthClient;
import com.orbitz.consul.KeyValueClient;
import com.orbitz.consul.NotRegisteredException;
import com.orbitz.consul.StatusClient;
import com.orbitz.consul.model.agent.ImmutableRegCheck;
import com.orbitz.consul.model.agent.ImmutableRegistration;
import com.orbitz.consul.model.agent.Registration;
import com.orbitz.consul.model.health.ServiceHealth;

/**
 * serviceName=ServiceInstance是服务实例<br/>
 * serviceCheck是程序中提供调用的方法接口，tcp接口使用ttl监测，web接口使用http接口监听
 * 
 * @author yangyong
 *
 */
public class ConsulClient {

	private Consul consul;

	public ConsulClient() {
		ConsulConfig config = Lambkit.config(ConsulConfig.class);
		consul = Consul.builder().withHostAndPort(HostAndPort.fromString(config.getAddress())).build();
	}

	public ConsulClient(String hostAndPort) {
		consul = Consul.builder().withHostAndPort(HostAndPort.fromString(hostAndPort)).build();
	}

	public AgentClient getAgentClient() {
		return consul.agentClient();
	}

	public void deregister(String serviceId) {
		AgentClient agent = consul.agentClient();
		agent.deregister(serviceId);
	}

	public void passCheck(String serviceId) throws NotRegisteredException {
		AgentClient agent = consul.agentClient();
		agent.passCheck(serviceId);
	}

	/**
	 * 服务注册
	 * 
	 * @param service
	 */
	public void registry(ConsulService service) {
		AgentClient agent = consul.agentClient();
		ImmutableRegistration.Builder builder = ImmutableRegistration.builder();
		builder.id(service.getId());
		builder.name(service.getName());
		builder.address(service.getIp());
		builder.port(service.getPort());

		if ("http".equals(service.getCheckType())) {
			// 健康检测
			StringBuffer interval = new StringBuffer(String.valueOf(service.getInterval()));
			interval.append("s");
			ImmutableRegCheck check = ImmutableRegCheck.builder().http(service.getUrl()).interval("10s")// interval.toString()
					.build();
			builder.addChecks(check);
		} else {
			builder.check(Registration.RegCheck.ttl(service.getInterval()));
		}
		builder.addAllTags(service.getTags());
		agent.register(builder.build());
	}

	/**
	 * 服务发现
	 * @param instanceName
	 * @return
	 */
	public List<ServiceHealth> discover(String instanceName) {
		// TODO Auto-generated method stub
		HealthClient client = consul.healthClient();
		// 获取所有服务
		// System.out.println(client.getAllServiceInstances(name).getResponse().size());

		// 获取所有正常的服务（健康检测通过的）
//        client.getHealthyServiceInstances(name).getResponse().forEach((resp) -> { 
//        	ServiceHealth sh = resp;
//            System.out.println(resp);  
//        });
		List<ServiceHealth> serviceHealthList = client.getHealthyServiceInstances(instanceName).getResponse();
		if (serviceHealthList == null)
			return null;
		for (ServiceHealth resp : serviceHealthList) {
			System.out.println("ServiceHealth: " + instanceName + ", " + resp.getService().getId());
		}
		return serviceHealthList;
	}
	
	/**
	 * 服务发现
	 * @param instanceName
	 * @param serviceId
	 * @return
	 */
	public ConsulService discover(String instanceName, String serviceId) {
		// TODO Auto-generated method stub
		HealthClient client = consul.healthClient();
		// 获取所有服务
		// System.out.println(client.getAllServiceInstances(name).getResponse().size());
		List<ServiceHealth> serviceHealthList = client.getHealthyServiceInstances(instanceName).getResponse();
		if (serviceHealthList == null)
			return null;
		ConsulService service = null;
		for (ServiceHealth resp : serviceHealthList) {
			if(serviceId.equals(resp.getService().getId())) {
				service = fromServiceHealth(instanceName, resp);
				break;
			}
		}
		return service;
	}

	private ConsulService fromServiceHealth(String instanceName, ServiceHealth resp) {
		String ip = resp.getService().getAddress();
		int port = resp.getService().getPort();
		ConsulService service = new ConsulService(instanceName, ip, port);
		service.setId(resp.getService().getId());
		service.setTags(resp.getService().getTags());
		
//		List<HealthCheck> checks = resp.getChecks();
//		for (HealthCheck healthCheck : checks) {
//			if(instanceName.equals(healthCheck.getName())) {
//				//service.setUrl(resp.getService().getAddress());
//			}
//		}
		List<String> tags = resp.getService().getTags();
		for (String tag : tags) {
			if(tag.startsWith("URL_")) {
				String url = tag.substring(4);
				service.setUrl(url);
			}
		}
		return service;
	}

	/**
	 * 存储KV
	 */
	public void storeKV(String key, String value) {
		KeyValueClient kvClient = consul.keyValueClient();
		kvClient.putValue(key, value);
	}

	/**
	 * 根据key获取value
	 */
	public String getKV(String key) {
		KeyValueClient kvClient = consul.keyValueClient();
		Optional<String> value = kvClient.getValueAsString(key);
		if (value.isPresent()) {
			return value.get();
		}
		return "";
	}

	public String containerKey(String key) {
		KeyValueClient kvClient = consul.keyValueClient();
		Optional<String> value = kvClient.getValueAsString(key);
		if (value.isPresent()) {
			return value.get();
		}
		return "";
	}

	/**
	 * 找出一致性的节点（应该是同一个DC中的所有server节点）
	 */
	public List<String> findRaftPeers() {
		StatusClient statusClient = consul.statusClient();
		return statusClient.getPeers();
	}

	/**
	 * 获取leader
	 */
	public String findRaftLeader() {
		StatusClient statusClient = consul.statusClient();
		return statusClient.getLeader();
	}

}
